package controller

import (
	"fmt"
	"gitee.com/saxon134/sysmain/api"
	"gitee.com/saxon134/sysmain/db"
	"gitee.com/saxon134/sysmain/db/models"
	"gitee.com/saxon134/sysmain/sdp"
	"github.com/saxon134/go-utils/saData"
	"github.com/saxon134/go-utils/saData/saTime"
	"github.com/saxon134/go-utils/saLog"
	"net/http"
	"time"
)

type AppItem struct {
	*models.TblApp
	Status    string      `json:"status"`
	Success   int         `json:"success"`
	Fail      int         `json:"fail"`
	Instances []*Instance `json:"instances"`
}

type Instance struct {
	App     string `json:"-"`
	Host    string `json:"host"`
	Port    int    `json:"port"`
	Success int    `json:"success"`
	Fail    int    `json:"fail"`
}

func AppList(w http.ResponseWriter, r *http.Request) {
	var ary = make([]*models.TblApp, 0, 10)
	err := db.MySql.Table(models.TBNApp).Order("id desc").Find(&ary).Error
	if db.MySql.IsError(err) {
		api.ResError(w, err.Error())
		return
	}

	//不需要返回实例数据
	withInstance, _ := saData.ToBool(r.URL.Query().Get("withInstance"))
	if withInstance == false {
		api.ResSuccess(w, ary)
		return
	}

	var resAry = make([]*AppItem, 0, len(ary))
	if len(ary) > 0 {
		for _, v := range ary {
			var key = fmt.Sprintf(sdp.RedisAppKey, v.App)
			var sdpAry = make([]*sdp.Instance, 0, 10)
			err = db.Redis.GetObj(key, &sdpAry)
			if db.Redis.IsError(err) {
				saLog.Err("SDP error:", err)
			}

			var m = &AppItem{
				TblApp: v,
				Status: "已停止",
			}

			if len(sdpAry) > 0 {
				m.Status = "运行中"
				m.Instances = make([]*Instance, 0, len(sdpAry))
				for _, s := range sdpAry {
					m.Instances = append(m.Instances, &Instance{
						Host: s.Host,
						Port: s.Port,
					})
				}
			}

			resAry = append(resAry, m)
		}

		var statsAry = make([]map[string]interface{}, 0, 40)
		db.MySql.Raw(`
			SELECT
				app,
				host,
				port,
				success,
				count( * ) cnt
			FROM
				stats_api 
			WHERE
				ts >= ? 
			GROUP BY
				app, host, port, success
		`, saTime.TimeToStr(time.Now(), saTime.FormatYMDHimple)).Scan(&statsAry)
		if len(statsAry) > 0 {
			for _, v := range resAry {
				for _, inst := range statsAry {
					app := saData.String(inst["app"])
					host := saData.String(inst["host"])
					port := saData.Int(inst["port"])
					success, _ := saData.ToBool(inst["success"])
					cnt := saData.Int(inst["cnt"])
					if app == v.App {
						if success {
							v.Success += cnt
						} else {
							v.Fail += cnt
						}

						for _, instance := range v.Instances {
							if instance.Host == host && instance.Port == port {
								if success {
									instance.Success += cnt
								} else {
									instance.Fail += cnt
								}
							}
						}
					}
				}
			}
		}
	}

	api.ResSuccess(w, resAry)
}

func HostList(w http.ResponseWriter, r *http.Request) {
	var ary = make([]*models.TblApp, 0, 10)
	err := db.MySql.Table(models.TBNApp).Order("id desc").Find(&ary).Error
	if db.MySql.IsError(err) {
		api.ResError(w, err.Error())
		return
	}

	var resAry = make([]string, 0, len(ary))
	if len(ary) > 0 {
		for _, v := range ary {
			var key = fmt.Sprintf(sdp.RedisAppKey, v.App)
			var sdpAry = make([]*sdp.Instance, 0, 10)
			_ = db.Redis.GetObj(key, &sdpAry)

			for _, instance := range sdpAry {
				resAry = append(resAry, instance.Host+":"+saData.String(instance.Port))
			}
		}
	}

	api.ResSuccess(w, resAry)
}
